/*
 * phdr.c
 *
 *  Created on: Sep 9, 2012
 *      Author: aortegag
 */

#include <stdlib.h>
#include <string.h>
#include "phdr.h"
#include "common.h"
#include "logging.h"

Elf64_Phdr *allocate_program_header_table(const Elf64_Ehdr *ehdr)
{
	if(!ehdr)
		return 0;

	if(ehdr->e_phnum == 0)
		return 0;

	return (Elf64_Phdr *)malloc(ehdr->e_phentsize * ehdr->e_phnum);
}


elf_code_t read_program_header_table(FILE *fd, const Elf64_Ehdr *ehdr, Elf64_Phdr *phdr) {
	if (!ehdr || !phdr)
		return ELF_PHDR_INVALID_ERROR;

	if (ehdr->e_phoff == 0)
		return ELF_PHDR_TABLE_NOT_FOUND;

	rewind(fd);
	fseek(fd, ehdr->e_phoff, SEEK_SET);

	size_t read = fread(phdr, sizeof(Elf64_Phdr), ehdr->e_phnum, fd);

	if (read != ehdr->e_phnum)
		return ELF_PHDR_READ_ERROR;

	return ELF_SUCCESS;
}


/**
 * \brief Pretty prints the Program Header table
 *
 * \note This function assumes a program header has been stored
 *  in the Elf structure.
 */
void	pretty_print_phdr(const Elf64_Ehdr *ehdr, const Elf64_Phdr *phdr)
{
	if(!phdr){
		LOG_ERR("Invalid Program Header table.\n");
		return;
	}
	if(ehdr->e_phnum == 0){
		LOG_INFO("Program Header table not available.\n");
		return;
	}
	int i =0;
	LOG_INFO("Entry point %#08x\n", (unsigned int)ehdr->e_entry);
	LOG_INFO("There are %d program headers, starting at offset %d (%#08x)\n\n",\
			ehdr->e_phnum,\
			(unsigned int)ehdr->e_phoff, (unsigned int)ehdr->e_phoff);

	LOG_INFO("Program headers:\n");
	LOG_INFO("===================================="\
				"=========================================\n");
	LOG_INFO("       Type\tOffset\t\t   VirtAddr\t      PhysAddr\n"\
			 "\t\tFileSize\t   MemSize\t      Flags\tAlign\n\n");
	const Elf64_Phdr *p = phdr;
	LOG_INFO("===================================="\
			"=========================================\n");
	for(i = 0; i < ehdr->e_phnum; i++){;
		LOG_INFO("%12s\t"\
				 "%#016x   "
				 "%#016x   "
				 "%#016x\n",\

				phdr_type(p[i].p_type),\
				(unsigned int)p[i].p_offset,\
				(unsigned int)p[i].p_vaddr,\
				(unsigned int)p[i].p_paddr
				);

		LOG_INFO("\n");

		LOG_INFO("\t\t%#016x   "
				 "%016x   "
				 "%s\t"
				 "%d"
				 "\n",\

				 (unsigned int)p[i].p_filesz,\
				 (unsigned int)p[i].p_memsz,\
				 phdr_flag_type(p[i].p_flags),\
				 (int)p[i].p_align\
				);
		LOG_INFO("===================================="\
				"=========================================\n");
	}
}

